import java.util.ArrayList;

public class GrammarRule {

	String ruleName;

	ArrayList<RulePiece> pieces;

	Grammar grammar;

	ArrayList<String> firstSet;

	boolean calc;
	
	int lineNumber;
	
	public GrammarRule(String info, Grammar g, String title, int lineNumber) {
		pieces = new ArrayList<RulePiece>();
		firstSet = new ArrayList<String>();
		grammar = g;
		calc = false;
		String s1;
		String s2;
		
		this.lineNumber=lineNumber;

		if (title.isEmpty()) {
			// Name
			s1 = info.substring(0, info.indexOf(' '));
			s2 = info.substring(info.indexOf(' ') + 1, info.indexOf('\n'));

			ruleName = s2.substring(0, s2.indexOf(' '));
			info = info.substring(info.indexOf('\n') + 1);

			// Equal sign
			s1 = info.substring(0, info.indexOf(' '));
			s2 = info.substring(info.indexOf(' ') + 1, info.indexOf('\n'));
			if (!s1.equals("$ASSIGN")) {
				System.out
						.println("ERROR: Second piece of line is not $ASSIGN");
			}

			info = info.substring(info.indexOf('\n') + 1);
		}
		else {
			ruleName = title;
		}
		
		// Rest of line
		while (info.indexOf('\n') > 0) {
			s1 = info.substring(0, info.indexOf(' '));
			s2 = info.substring(info.indexOf(' ') + 1, info.indexOf('\n'));

			while (s2.charAt(s2.length() - 1) == ' ') {
				s2 = s2.substring(0, s2.length() - 1);
			}

			if (s1.equalsIgnoreCase("$OR")) {
				grammar.addGrammarRule(new GrammarRule(info.substring(info
						.indexOf('\n') + 1), grammar,ruleName,lineNumber));

				info = "";
			} else {
				addRulePiece(s1, s2, lineNumber);

				info = info.substring(info.indexOf('\n') + 1);
			}
		}

	}

	public void addRulePiece(String type, String content, int lineNumber) {
		addRulePiece(new RulePiece(type, content,lineNumber));
	}

	public void addRulePiece(RulePiece r) {
		pieces.add(r);
	}

	public RulePiece getPiece(int i) {
		return pieces.get(i);

	}

	public int numPieces() {
		return pieces.size();
	}

	public String toString() {

		String r = ruleName + " ::= ";

		for (int i = 0; i < pieces.size(); i++) {
			r += pieces.get(i).getContent() + " ";
		}
		return r;
	}
	
	public String piecesToString(){
		
		String r= "";
		for (int i = 0; i < pieces.size(); i++) {
			r += pieces.get(i).getContent() + " ";
		}
		return r.substring(0,r.length()-1);
	}

	public String getName() {
		return ruleName;

	}

	@SuppressWarnings("unchecked")
	public ArrayList<String> getFirstSet() {

		return (ArrayList<String>) firstSet.clone();

	}

	public void calculateFirstSet() {

		if (!calc) {
			RulePiece rp = pieces.get(0);

			if (rp.getType().equals("$RULE")) {

				for (int i = 0; i < grammar.numRules(); i++) {
					if (grammar.getRule(i).getName().equals(rp.getContent())) {
						grammar.getRule(i).calculateFirstSet();
						firstSet.addAll(grammar.getRule(i).getFirstSet());
					}
				}
			}
			if (rp.getType().equals("$TERMINAL")||rp.getType().equals("$SPEC")) {
				firstSet.add(rp.getContent());
			}
		}
		calc = true;
	}
}
